/**
 * 
 */
package controller.xml;

import model.ParameterValue;
import model.solver.MiniSatParameter;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * Use to parse a {@link MiniSatParameter} in the exported session in XML.
 * 
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class MiniSatParameterXMLHandler extends XMLHandler {

	private MiniSatParameter			param	= null;
	private MiniSatParameterXMLStatus	status	= MiniSatParameterXMLStatus.NONE;

	// private SolverParameterXMLHandler paramHandler = null;

	public MiniSatParameterXMLHandler() {
	}


	@Override
	public boolean characters2(char[] ch, int start, int length) throws SAXException {

		switch (status) {
		case NONE:
		case SOLVER_PARAMETER:
			throw new SAXException("not supposed to receive character in this status");
		default:
			return super.characters2(ch, start, length);
		}
	}

	@Override
	public boolean endDocument2() throws SAXException {
		return false;
	}

	@Override
	public boolean endElement2(String uri, String localName, String qName) throws SAXException {
		switch (status) {
		case NONE:
			return false;

		case SOLVER_PARAMETER:
			if (qName.equals(XMLBaliseFormat.SOLVER_PARAMETER))
			{// ferme basic param
				status = MiniSatParameterXMLStatus.NONE;
				param = new MiniSatParameter(((SolverParameterXMLHandler) delegate).getParam());
				delegate = null;
				return true;
			}
			throw new SAXException("end of SOLVER PARAMETER was expected");

		case ASYMM:
			if (qName.equals(XMLBaliseFormat.MINISAT_ASYMM))
			{// ferme asymm
				setAsymm();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of ASYMM was expected");
		case DECAY:
			if (qName.equals(XMLBaliseFormat.MINISAT_DECAY))
			{// ferme decay
				setDecay();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of decay was expected");

		case GROW:
			if (qName.equals(XMLBaliseFormat.MINISAT_GROY))
			{// ferme grow
				setGrow();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of GROW was expected");

		case POLARITY:
			if (qName.equals(XMLBaliseFormat.MINISAT_POLARITY))
			{// ferme polarity
				setPolarity();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of POLARITY was expected");

		case PRE:
			if (qName.equals(XMLBaliseFormat.MINISAT_PRE))
			{// ferme pre
				setPre();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of PRE was expected");

		case RCHECK:
			if (qName.equals(XMLBaliseFormat.MINISAT_RECHECK))
			{// ferme rcheck
				setRcheck();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of RCHECK was expected");

		case RNDFREQ:
			if (qName.equals(XMLBaliseFormat.MINISAT_RNDFREQ))
			{// ferme solution
				setRndfreq();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of RNDFREQ was expected");

		case VERBOSITY:
			if (qName.equals(XMLBaliseFormat.MINISAT_VERBOSITY))
			{// ferme solution
				setVerbosity();
				status = MiniSatParameterXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of VERBOSITY was expected");

		}
		// attend une fin de balise qui existe pas...
		throw new SAXException("an other end of element was expected");
	}

	@Override
	public boolean startElement2(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {
		if (status != MiniSatParameterXMLStatus.NONE)
			throw new SAXException("already have a started element");

		if (arg2.equals(XMLBaliseFormat.SOLVER_PARAMETER))
		{// balise parameter
			if (param != null)
				throw new SAXException("already have a SOLVER PARAMETER");

			// set les donnees pour recupere le basic result
			status = MiniSatParameterXMLStatus.SOLVER_PARAMETER;
			delegate = new SolverParameterXMLHandler();

			return true;
		}

		// si pas de param refuse les autres
		if (param == null)
			throw new SAXException("need a SOLVER PARAMETER	 first");

		if (arg2.equals(XMLBaliseFormat.MINISAT_ASYMM))
		{// balise asymm
			status = MiniSatParameterXMLStatus.ASYMM;
			return true;
		}
		if (arg2.equals(XMLBaliseFormat.MINISAT_DECAY))
		{// balise decay
			status = MiniSatParameterXMLStatus.DECAY;
			return true;
		}
		if (arg2.equals(XMLBaliseFormat.MINISAT_GROY))
		{// balise grow
			status = MiniSatParameterXMLStatus.GROW;
			return true;
		}
		if (arg2.equals(XMLBaliseFormat.MINISAT_POLARITY))
		{// balise polarity
			status = MiniSatParameterXMLStatus.POLARITY;
			return true;
		}
		if (arg2.equals(XMLBaliseFormat.MINISAT_PRE))
		{// balise pre
			status = MiniSatParameterXMLStatus.PRE;
			return true;
		}
		if (arg2.equals(XMLBaliseFormat.MINISAT_RECHECK))
		{// balise rcheck
			status = MiniSatParameterXMLStatus.RCHECK;
			return true;
		}
		if (arg2.equals(XMLBaliseFormat.MINISAT_RNDFREQ))
		{// balise rndfreq
			status = MiniSatParameterXMLStatus.RNDFREQ;
			return true;
		}
		if (arg2.equals(XMLBaliseFormat.MINISAT_VERBOSITY))
		{// balise verbosity
			status = MiniSatParameterXMLStatus.VERBOSITY;
			return true;
		}


		// peut pas commencer balise qui existe pas
		throw new SAXException("unexpected balise: " + arg2);
	}

	/**
	 * Return the param.
	 * 
	 * @return the param
	 */
	public MiniSatParameter getParam() {
		return param;
	}

	/**
	 * Set pre in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setPre() throws SAXException {
		String tmp = buffer.toString();
		if (tmp.equals(XMLBaliseFormat.TRUE))
			param.setPre(true);
		else
			if (tmp.equals(XMLBaliseFormat.FALSE))
				param.setPre(false);
			else
				throw new SAXException("unkwown value for PRE");
	}

	/**
	 * Set asymm in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setAsymm() throws SAXException {
		param.setAsymm(ParameterValue.getValueFromXML(buffer.toString()));
		if (param.getAsymm() == null)
			throw new SAXException("asymm unknown");
	}

	/**
	 * Set rcheck in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setRcheck() throws SAXException {
		if (!param.setRcheck(ParameterValue.getValueFromXML(buffer.toString())))
			throw new SAXException("bad rcheck");
		if (param.getRcheck() == null)
			throw new SAXException("rcheck unknown");
	}

	/**
	 * Set polarity in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setPolarity() throws SAXException {
		param.setPolarityMode(ParameterValue.getValueFromXML(buffer.toString()));
		if (param.getRcheck() == null)
			throw new SAXException("polarity mode unknown");
	}

	/**
	 * Set grow in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setGrow() throws SAXException {
		Integer val = null;
		try
		{
			val = Integer.valueOf(buffer.toString());
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for GROW");
		}
		if (!param.setGrow(val))
			throw new SAXException("bad grow");
	}

	/**
	 * Set verbosity in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setVerbosity() throws SAXException {
		Integer verb = null;
		try
		{
			verb = Integer.valueOf(buffer.toString());
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for VERBOSITY");
		}
		if (!param.setVerbosity(verb))
			throw new SAXException("bad verbosity");
	}

	/**
	 * Set decay in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setDecay() throws SAXException {
		Double dec = null;
		try
		{
			dec = Double.valueOf(buffer.toString());
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for DECAY");
		}
		if (!param.setDecay(dec))
			throw new SAXException("bad decay");
	}

	/**
	 * Set rndfreq in the {@link MiniSatParameter}.
	 * 
	 * @throws SAXException
	 */
	private void setRndfreq() throws SAXException {
		Double rnd = null;
		try
		{
			rnd = Double.valueOf(buffer.toString());
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for RNDFREQ");
		}
		if (!param.setRndfreq(rnd))
			throw new SAXException("bad rnd");
	}
}
